package org.budo.graph.service.impl;

import org.budo.graph.entity.DubboProvider;
import org.budo.graph.service.util.ActiveConnectionsUtil;
import org.budo.graph.service.util.AvailableFontsUtil;
import org.budo.graph.service.util.BudoMetricUtil;
import org.budo.graph.service.util.BudoUpstreamUtil;
import org.budo.graph.service.util.ClassPathUtil;
import org.budo.graph.service.util.DatabaseMetadataUtil;
import org.budo.graph.service.util.DubboEchoUtil;
import org.budo.graph.service.util.DubboServiceUtil;
import org.budo.graph.service.util.EhcacheStatisticsUtil;
import org.budo.graph.service.util.FileExplorerUtil;
import org.budo.graph.service.util.GitLogUtil;
import org.budo.graph.service.util.GraphSentinelUtil;
import org.budo.graph.service.util.GraphServiceUtil;
import org.budo.graph.service.util.GraphShardingUtil;
import org.budo.graph.service.util.GraphSpringUtil;
import org.budo.graph.service.util.LogLevelUtil;
import org.budo.graph.service.util.MemoryMapUtil;
import org.budo.graph.service.util.MethodRequestUtil;
import org.budo.graph.service.util.MybatisMapperUtil;
import org.budo.graph.service.util.PerfCountUtil;
import org.budo.graph.service.util.PlaceholderUtil;
import org.budo.graph.service.util.RedisPoolUtil;
import org.budo.graph.service.util.SessionRequestUtil;
import org.budo.graph.service.util.SpringTaskUtil;
import org.budo.graph.service.util.SqlRequestUtil;
import org.budo.graph.service.util.SystemInfoUtil;
import org.budo.graph.service.util.SystemPropertyUtil;
import org.budo.graph.service.util.ThreadInfoUtil;
import org.budo.graph.service.util.TopProcessUtil;
import org.budo.graph.service.util.TopThreadUtil;
import org.budo.graph.view.util.DubboProviderUtil;
import org.budo.support.application.registry.BudoApplicationUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.alibaba.druid.stat.DruidStatService;

import lombok.Getter;
import lombok.Setter;
import redis.clients.jedis.JedisPool;

/**
 * @author lmw
 */
@Getter
@Setter
public class SpringBudoGraphServiceImpl extends AbstractBudoGraphService implements ApplicationContextAware, InitializingBean {
    private static final Logger log = Slf4j.getLogger();

    private static final boolean IS_BUDO_ENV = ReflectUtil.hasClass("org.budo.module.account.service.entity.User");

    private ApplicationContext applicationContext;

    public SpringBudoGraphServiceImpl() {
    }

    public SpringBudoGraphServiceImpl(ApplicationContext applicationContext) {
        this.setApplicationContext(applicationContext);
    }

    public void afterPropertiesSet() throws Exception {
        this.scheduleTimerTask();
    }

    public String serviceDubboDruidStat(String url) {
        if (null == url || "null".equalsIgnoreCase(url)) {
            return "#75, serviceDubboDruidStat, url=" + url;
        }

        if (IS_BUDO_ENV && StringUtil.startsWith(url, "/file-explorer")) {
            return FileExplorerUtil.writeFileExplorerResponse(url);
        }

        ApplicationContext applicationContext = this.getApplicationContext();
        String applicationName = BudoApplicationUtil.getApplicationName();
        JedisPool jedisPool = this.jedisPool();

        String response = this.serviceApi(url, applicationContext, applicationName, jedisPool);
        if (null != response) {
            return response;
        }

        DruidStatService druidStatService = DruidStatService.getInstance();
        if (null == druidStatService) {
            return "#157 DRUID_STAT_SERVICE_INSTANCE_IS_NULL";
        }

        log.info("#122 druidStatService.service, url=" + url);
        return druidStatService.service(url);
    }

    private String serviceApi(String url, ApplicationContext applicationContext, String applicationName, JedisPool jedisPool) {
        if (StringUtil.startsWith(url, "/budo-metric") || StringUtil.startsWith(url, "/healthz")) {
            return BudoMetricUtil.budoMetric(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/upstream")) {
            return BudoUpstreamUtil.upstream(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/dubbo-service.json")) {
            return DubboServiceUtil.writeDubboServiceJson(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/dubbo-reference.json")) {
            return DubboEchoUtil.writeDubboReference(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/dubbo-echo")) {
            return DubboEchoUtil.writeDubboEcho(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/dubbo-service")) {
            return DubboServiceUtil.writeDubboService(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/sql.json")) {
            return GraphServiceUtil.sqlListData(url);
        }

        if (StringUtil.startsWith(url, "/table-sql.json")) {
            return GraphServiceUtil.sqlListData(url);
        }

        if (StringUtil.startsWith(url, "/spring.json")) {
            return GraphServiceUtil.springMethodStatData(url);
        }

        if (StringUtil.startsWith(url, "/spring-method.json")) {
            return GraphServiceUtil.springMethodStatData(url);
        }

        if (StringUtil.startsWith(url, "/weburi.json")) {
            return GraphServiceUtil.webUriListData(url);
        }

        if (StringUtil.startsWith(url, "/metric.json")) {
            return GraphServiceUtil.metricList(url);
        }

        if (StringUtil.startsWith(url, "/metric-ref.json")) {
            return GraphServiceUtil.metricList(url);
        }

        if (StringUtil.startsWith(url, "/websession.json")) {
            return GraphServiceUtil.websessionStatData(url);
        }

        if (StringUtil.startsWith(url, "/weburi-") && url.indexOf(".json") > 0) {
            return GraphServiceUtil.webUriStatData(url);
        }

        if (StringUtil.startsWith(url, "/line-graph.json")) {
            return this.getBudoGraphRepository().readLine(url, applicationName);
        }

        if (StringUtil.startsWith(url, "/graph-data-clear.json")) {
            return this.getBudoGraphRepository().removeData(url);
        }

        if (StringUtil.startsWith(url, "/graph-data.json")) {
            return this.getBudoGraphRepository().readTable_json(url);
        }

        if (StringUtil.startsWith(url, "/graph-data")) {
            return this.getBudoGraphRepository().readTable(url);
        }

        if (StringUtil.startsWith(url, "/system-property")) {
            return SystemPropertyUtil.writeSystemPropertyResponse(url);
        }

        if (StringUtil.startsWith(url, "/log-level")) {
            return LogLevelUtil.writeLogLevelResponse(url);
        }

        if (StringUtil.startsWith(url, "/spring-bean")) {
            return GraphSpringUtil.writeSpringBeanResponse(url);
        }

        if (StringUtil.startsWith(url, "/placeholder")) {
            return PlaceholderUtil.writePlaceholderResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/system-info")) {
            return SystemInfoUtil.writeSystemInfoResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/class-path")) {
            return ClassPathUtil.writeClassPathResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/git-log")) {
            return GitLogUtil.writeGitLogResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/active-connections")) {
            return ActiveConnectionsUtil.writeActiveConnectionsResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/available-fonts")) {
            return AvailableFontsUtil.writeAvailableFontsResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/ehcache-statistics")) {
            return EhcacheStatisticsUtil.writeEhcacheStatisticsResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/redis-pool")) {
            return RedisPoolUtil.writeRedisPoolResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/database-metadata")) {
            return DatabaseMetadataUtil.writeDatabaseMetadataResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/thread-info")) {
            return ThreadInfoUtil.writeThreadInfoResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/memory-map")) {
            return MemoryMapUtil.writeMemoryMapResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/perf-count")) {
            return PerfCountUtil.writePerfCountResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/top-process")) {
            return TopProcessUtil.writeTopProcessResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/top-thread")) {
            return TopThreadUtil.writeTopThreadResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/sql-request")) {
            return SqlRequestUtil.writeSqlRequestResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/method-request")) {
            return MethodRequestUtil.writeMethodRequestResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/session-request")) {
            return SessionRequestUtil.writeSessionRequestResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/mybatis-mapper")) {
            return MybatisMapperUtil.writeMybatisMapperResponse(applicationContext, url);
        }

        if (StringUtil.startsWith(url, "/spring-task")) {
            return SpringTaskUtil.writeSpringTaskResponse(applicationContext, url);
        }

        if (StringUtil.contains(url, "/sentinel/update.api")) {
            return GraphSentinelUtil.update(applicationContext, url);
        }

        if (StringUtil.contains(url, "/sharding.api")) {
            return GraphShardingUtil.show(applicationContext, url);
        }

        if (StringUtil.contains(url, "/sharding-update.api")) {
            return GraphShardingUtil.update(applicationContext, url);
        }

        return null;
    }

    public DubboProvider dubboProviderMetadata() {
        ApplicationContext applicationContext = this.getApplicationContext();
        return DubboProviderUtil.getDubboProviderFromApplicationContext(applicationContext);
    }
}
